package cn.matezk.lianlian.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.net.URLEncoder;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.matezk.lianlian.dao.DeviceDao;
import cn.matezk.lianlian.dao.PaymentOrderDao;
import cn.matezk.lianlian.dao.PaymentOrderDetailDao;
import cn.matezk.lianlian.framework.RedisMutexLock;
import cn.matezk.lianlian.model.Device;
import cn.matezk.lianlian.model.PaymentOrder;
import cn.matezk.lianlian.model.PaymentOrderDetail;
import cn.matezk.lianlian.service.IPaymentService;
import com.wechat.pay.java.service.payments.model.Transaction;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.nio.charset.Charset;
import java.util.*;

@Service
@Slf4j
public class PaymentService implements IPaymentService {
    @Autowired
    private RedisMutexLock mutexLock;
    @Autowired
    private DeviceDao deviceDao;
    @Autowired
    private PaymentOrderDao paymentOrderDao;
    @Autowired
    private PaymentOrderDetailDao paymentOrderDetailDao;

    private static final String API_ID = "CDMTZKKJYXGS1184@2024";
    private static final String API_KEY = "437bebe90638a6a3";
    private static final String API_PWD = "fa6fb09698305e9c";

    @Override
    public void doNotify(Transaction transaction) throws InterruptedException {
        String orderLockKey = PaymentOrder.createLockKey(transaction.getOutTradeNo());
        if (mutexLock.tryLock(orderLockKey, 20)) {
            try {
                PaymentOrder paymentOrder = paymentOrderDao.selectByPrimaryKey(transaction.getOutTradeNo());
                paymentOrder.setState(transaction.getTradeState().name());
                paymentOrder.setStateDesc(transaction.getTradeStateDesc());
                paymentOrder.setSuccessTime(DateUtil.parseUTC(transaction.getSuccessTime()));
                int count = paymentOrderDao.updateByPrimaryKeySelective(paymentOrder);
                if (count > 0 && Transaction.TradeStateEnum.SUCCESS.equals(transaction.getTradeState())) {
                    List<PaymentOrderDetail> details = paymentOrderDetailDao.selectByOrderId(paymentOrder.getOrderId());
                    for (PaymentOrderDetail item : details) {
                        String deviceLockKey = Device.createLockKey(item.getDeviceId());
                        if (mutexLock.tryLock(deviceLockKey, 3)) {
                            try {
                                Device device = deviceDao.selectByPrimaryKey(item.getDeviceId());
                                if (PaymentOrder.TYPE_NF.equals(paymentOrder.getChargeType())) {
                                    Calendar calendar = Calendar.getInstance();
                                    calendar.setTime(device.getExpireDate());
                                    if (ObjectUtil.isNull(item.getMonths()) || item.getMonths().intValue() == 0) {
                                        calendar.add(Calendar.YEAR, item.getAmount() / 1000);
                                    } else {
                                        calendar.add(Calendar.MONTH, item.getMonths());

                                    }
                                    Date expireDate = calendar.getTime();
                                    deviceDao.updateExpireDate(item.getDeviceId(), expireDate);
                                    if (ObjectUtil.equals("EZ", device.getCardSource()) && device.getCardState() == 3) {
                                        // 修改卡状态为激活
                                        if (erzStateChange(device.getIccid(), 0)) {
                                            deviceDao.updateIccidState(device.getIccid(), 1);
                                        }
                                    }
                                } else {
                                    int amount = device.getAmount().intValue() + item.getAmount();
                                    deviceDao.updateAmount(item.getDeviceId(), amount);
                                }
                            } finally {
                                mutexLock.unlock(deviceLockKey);
                            }
                        } else {
                            throw new InternalError(String.format("未获取到设备锁: %s", transaction.getOutTradeNo()));
                        }
                    }
                }
            } finally {
                mutexLock.unlock(orderLockKey);
            }
        } else {
            throw new InternalError(String.format("未获取到订单锁: %s", transaction.getOutTradeNo()));
        }
    }

    private boolean erzStateChange(String iccid, Integer state) {
        Map<String, Object> form = new HashMap<>();
        form.put("id", API_ID);
        String body = JSONUtil.createObj()
                .set("pwd", API_PWD)
                .set("method", "disabledNumber")
                .set("iccid", iccid)
                .set("typeid", String.format("%d", state))
                .toString();
        form.put("info", XorEncryptAndBaseNew(body, API_KEY));
        String response = HttpUtil.post("http://global.anhuiyk.cn:8006/m2m_api/v1/query/", form);
        log.info(response);
        JSONObject obj = JSONUtil.parseObj(response);
        return ObjectUtil.equals("0", obj.getStr("resultCode"));
    }

    public static String XorEncryptAndBaseNew(String str,String key) {
        byte[] b1 = str.getBytes();
        byte[] b2 = key.getBytes();
        byte[] out = new byte[b1.length];
        for (int i = 0; i < b1.length; i++) {
            out[i] = (byte) (b1[i] ^ b2[i % b2.length]);
        }
        return new URLEncoder().encode(Base64.getEncoder().encodeToString(out), Charset.defaultCharset());
    }
}
